BPVC - Computational design report

1. Departments Stacking

Il primo studio riguarda l'ottimizzazione della distribuzione dei dipartimenti sui livelli dell’edificio.

Adjacencies Matrix

Compilazione della matrice delle prossimitĆ  dei dipartimenti. Oltre alla matrice vengono inserite anche le aree di programma, le aree di progetto e l’indicazione dei livelli su cui possono essere ospitati i dipartimenti.

Algoritmo generativo

L’algoritmo generativo ĆØ la componente principale di tutto il processo. E’ l’insieme di regole che consentono di creare le migliaia di opzioni, che poi verranno valutate ed esplorate nei passaggi successivi.

In questo caso ĆØ stato impostato uno script in Grasshopper in cui i valori assegnati alle variabili (sliders), generano composizioni di stacking ogni volta diverse.

Algoritmo di valutazione

Gli algoritmi di valutazione ricevono le opzioni dal generatore e, assegnando un valore, ne valutano la performance.
In questo caso vengono valutati tre parametri:

  • Unplaced area: totale di area di programma non posizionata (valore da minimizzare)
  • Adjacency: sommatoria delle prossimitĆ  positive. Per i dipartimenti posizionati sullo stesso piano vengono selezionati dalla matrice i reciproci valori di prossimitĆ  assegnando i seguenti valori numerici: A=10, B=5, D=2. (valore da massimizzare)
  • Negative Adjacency: sommatoria delle prossimitĆ  negative. (valore da minimizzare)

Generative Design Engine

Il generative design engine, chiamato anche solver, ĆØ un’applicazione software che esegue molte volte in automatico uno script, che contiene sia l’algoritmo generativo che quello valutativo.
Variando più volte la posizione degli slider, ottiene una grande quantità di opzioni diverse e le relative valutazioni. In questo caso sono stati utilizzati due metodi di generazione delle opzioni:

  • CROSS PRODUCT: consente di esplorare l’intero campo di opzioni possibili, generate da tutte le combinazioni, ottenute posizionando ogni variabile su una serie discreta di valori all’interno del loro range.
  • OPTIMIZE: consente di ottenere le opzioni con le performance migliori. algoritmo di tipo genetico (multi-objective optimization), che crea diverse ā€œgenerazioniā€ (o iterazioni), dove ogni iterazione usa come configurazione gli input della generazione precedente associati ai risultati migliori.

    Optimize - Nella schermata si nota come l'algoritmo di ottimizzazione tenda a far convergere i valori dei parametri di valutazione verso i valori ottimali


    Cross Product - Grafico a coordinate parallele


    Cross Product - Scatter plot

Design Space Exploration (DSE)

La design space exploration (DSE) ĆØ un processo di analisi sistematica delle moltissime design option ottenute. L’obiettivo ĆØ quello di analizzare i dati per una progressiva scrematura, fino a raggiungere un numero di opzioni accettabile e rappresentativo del design space.
La DSE può essere suddivisa in diversi step, in cui il numero di opzioni viene ridotto ad ogni passaggio.

Prima fase:

Analisi dei dati eseguita con strumenti di programmazione Python e tecniche di unsupervised machine learning, che consentono di scremare le opzioni e selezionarne un numero ristretto.

In [15]:
%%javascript
$('.input').children('.inner_cell').hide();
In [1]:
# Import 
import json
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
import seaborn as sns  
from sklearn import metrics  
import plotly
import plotly.graph_objects as go
import plotly.express as px

projectName = "BPVC"

# Dataframe from GD Autodesk
df = pd.read_csv('../DSE/000000-CVP-CD-01-X-DY-Departments 012.csv')
studyName = "GD012"

# Dataframe from Wallacei
#df = pd.read_excel('../DSE/BPVC-WLC Results.xlsx')
#studyName = "WLC"

df
Out[1]:
ID posAdj negAdj depLeftoverArea depsLev0 depsLev1 depsLev2 depsLev3 depsLev4 levsOrder Generation created Is solution optimal?
0 ec7a6e0e-cf2b-47cb-8816-074afe8c0bb2 231 0 1680 30734 85 213341178 261832 9223 112 1 False
1 7f9a37c2-8f9d-479d-8b5c-80cad3ffa62a 221 30 235 20250 39596 369081816 195816 34686 28 1 False
2 97491116-71ab-4c5f-82fd-4efe7eeb0c53 269 20 1565 22982 8057 241761911 175969 14385 41 1 False
3 c6b45ad6-a5e5-426e-8645-a9ad8e7e3211 251 120 0 10293 33938 322422455 30204 673 2 1 False
4 7a312607-772a-4c58-bd19-7aebe0362aa8 253 70 700 10217 19233 47962020 236615 1597 1 1 False
... ... ... ... ... ... ... ... ... ... ... ... ...
7052 8401ae45-488e-4569-9d96-fdb323262f6d 188 110 1510 15351 12076 284644459 63505 22223 4 99 False
7053 4013b2af-0c36-47ea-963e-1420fe867838 228 40 1625 18049 25743 180425924 65676 12911 5 99 False
7054 a7168528-fd4c-470d-8792-6ec0e05f5694 319 0 30 18369 27182 183461055 41811 21689 4 99 False
7055 6d7d80da-9ffa-4585-8522-907eb2912320 319 0 30 18369 27182 183461055 41811 21689 4 99 False
7056 eb39b080-b653-43db-9226-3ac9eec372a7 319 0 30 18369 27182 183461055 41811 21689 4 99 False

7057 rows Ɨ 12 columns

Gli strumenti utilizzati sono:

  • Grafico a coordinate parallele per filtrare le opzioni in base ai risultati numerici ed eliminare le peggiori.
In [2]:
fig = go.Figure(data=
    go.Parcoords(labelfont = {'family': "Arial",
                    'size': 14
                },
                line = dict(color = df['posAdj'],
                   colorscale = 'tealrose',
                   showscale = True,
                    colorbar = {'tickfont': {'size': 14
                                    
                                }
                               },
                   ),
                dimensions = list([
                    dict(label = "Adjacency", values = df['posAdj']),
                    dict(label = 'Remote', values = df['negAdj']),
                    dict(label = 'Departments Leftover Area', values = df['depLeftoverArea']),
                    
                    #dict(label = 'Levels Leftover Area', values = df['levLeftoverArea'])
                ])
                ),
                
)   

fig.show()
  • Pairplots: per analizzare eventuali correlazioni tra i parametri, sia di generazione che di valutazione.
In [3]:
df_ToCluster = df.loc[(df['posAdj'] >= 150) & (df['negAdj'] >= -80)]

df_ToCluster = df_ToCluster[['posAdj','negAdj','depLeftoverArea']]

sns.set()
sns_plot = sns.pairplot(df_ToCluster)
  • Clustering: per raggruppare opzioni con risultati simili. Selezionando un solo rappresentante per ogni cluster (centro del cluster), si ottiene un campione ridotto che sia comunque rappresentativo di tutto il design space.
In [4]:
scaler = StandardScaler()
scaled_array = scaler.fit_transform(df_ToCluster)
scaled_dataframe = pd.DataFrame( scaled_array, columns = df_ToCluster.columns )

kmeans_model = KMeans(n_clusters = 10)
kmeans_model.fit(scaled_dataframe)

df_ToCluster["cluster"] = kmeans_model.labels_
scaled_dataframe["cluster"] = kmeans_model.labels_

fig = go.Figure(data=[go.Scatter3d(
                x=df_ToCluster['posAdj'],
                y=df_ToCluster['negAdj'],
                z=df_ToCluster['depLeftoverArea'],
                mode='markers',
                marker=dict(
                    size=12,
                    color=df_ToCluster['cluster'],                # set color to an array/list of desired values
                    colorscale='geyser',   # choose a colorscale
                    opacity=0.8,
                    colorbar = {'tickvals': df_ToCluster['cluster'].tolist(),
                                  'ticktext': df_ToCluster['cluster'].tolist(),
                                'tickfont': {'size': 14},
                               },
))])
fig.update_layout(scene = dict(
                    xaxis_title='Sun Exposure',
                    yaxis_title='View to Park',
                    zaxis_title='Summer Rad RS'),
                  margin=dict(l=0, r=0, b=0, t=0))

fig.show()
In [5]:
sns.set()
sns_plot = sns.pairplot(data = df_ToCluster, hue = "cluster", palette = "Spectral")

Seconda fase:

Esplorazione delle singole opzioni </div> </div>

2. Space Planning

Dopo aver impostato lo stacking e di conseguenza il posizionamento dei dipartimenti su ogni livello, stiamo studiando un workflow che agevoli lo space planning dei piani.

1. Adjacencies Matrix (per piano)

Come giĆ  fatto per i dipartimenti, viene compilata la matrice delle adiacenze, per le funzioni di piano.

</div> </div>

2. Bubble graph (Syntactic e Gephi)

Abbiamo sperimentato diversi metodi che generano in automatico un grafico a bolle che massimizza la vicinanza dei nodi collegati tra di loro.

</div> </div>

Space Syntax graphs

Next steps: Space Planning - Hypar

Space planning functions

Test-fit functions

In [14]:
%%javascript
function toggler(){
    if(window.already_toggling){
        // Don't add multiple buttons.
        return 0
    }
    let btn = $('.input').append('<button>Toggle Code</button>')
        .children('button');
    $('.input').children('.inner_cell').hide();
    btn.on('click', function(e){
        let tgt = e.currentTarget;
        $(tgt).parent().children('.inner_cell').toggle()
    })
    window.already_toggling = true;
}

setTimeout(toggler, 5000);
In [8]:
!jupyter nbconvert BPVC-Report.ipynb --to html --template classic
[NbConvertApp] Converting notebook BPVC-Report.ipynb to html
[NbConvertApp] Writing 4531226 bytes to BPVC-Report.html